package com.itesm.sistemasinteligentes.sat;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String args[]) {
		String path = args[0];
		File folder = new File(path);
		File[] listOfFiles = folder.listFiles();
		int maxThreads = Integer.parseInt(args[1]);
		//This for iterates over every file in the folder provided in path variable
		for (int i = 0; i < listOfFiles.length; i++) {
			//This for iterates executing every file first using 1 thread then 2 threads... until maxThreads.
			for (int j = 1; j <= maxThreads; j++) {
				if (listOfFiles[i].isFile()) {
					System.out.println("Ejecutando pruebas con archivo "
							+ listOfFiles[i].getName());
					System.out.println("Hilos utilizados " + j);
					String actualFile = path + listOfFiles[i].getName();
					List<SATSolver> solvers = new ArrayList<SATSolver>();
					startSolvers(j, actualFile, solvers);				
					waitUntilSolvedOrTriesExausted(j, solvers);
					sendStopSignalToSolvers(solvers);

					// SATSolver sasat = new SASAT(
					// demacsToArray(path),
					// 100, 1, 100000 , 1000000);
					// solution = sasat.solve();
					// if (!solution) {
					// System.out
					// .println("No fue posible encontrar una solución al problema de SAT");
					// } else {
					// System.out.println(sasat.report());
					// }
				}
			}
		}

	}

	private static void sendStopSignalToSolvers(List<SATSolver> solvers) {
		for (SATSolver solver : solvers) {
			solver.stopThread = true;
		}
	}

	private static void waitUntilSolvedOrTriesExausted(int numberOfThreads,
			List<SATSolver> solvers) {
		boolean solutionFound = false;
		int failure = 0;
		while (!solutionFound) {
			for (SATSolver solver : solvers) {
				if (solver.solutionFound) {
					solutionFound = true;
				}
				if (solver.solverFinished) {
					failure++;
				}
				if (failure == numberOfThreads) {
					return;
				}
			}
		}
	}

	private static void startSolvers(int numberOfThreads, String filePath,
			List<SATSolver> solvers) {
		for (int i = 0; i < numberOfThreads; i++) {
			SATSolver gsat = new GSAT(demacsToArray(filePath),
					80, 10000);
			solvers.add(gsat);
			new Thread(gsat).start();
		}
	}

	private static int[][] demacsToArray(String path) {
		int[][] clauses = null;
		int clause = 0;
		try {
			// Open the file that is the first
			// command line parameter
			FileInputStream fstream = new FileInputStream(path);
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			// Read File Line By Line
			while ((strLine = br.readLine()) != null) {
				if (strLine.charAt(0) == 'p') {
					clauses = new int[Integer.parseInt(strLine.trim().split(
							"\\s+")[3])][3];
					break;
				}
			}
			while ((strLine = br.readLine()) != null) {
				// Print the content on the console
				String[] variables = strLine.trim().split("\\s+");
				clauses[clause][0] = Integer.parseInt(variables[0]);
				clauses[clause][1] = Integer.parseInt(variables[1]);
				clauses[clause][2] = Integer.parseInt(variables[2]);
				clause++;
			}
			// Close the input stream
			in.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}

		return clauses;
	}
}
